<template>
    <div>
      <!-- 功能区 -->
      <el-row>
        <label>下载文件结构: </label>
        <el-radio-group v-model="struct">
          <el-radio size="small" label="parallel">平行</el-radio>
          <el-radio size="small" label="struct">树状</el-radio>
        </el-radio-group>
      </el-row>

      <!-- 变更文件树和文件功能 -->
      <el-row class="margin-top">
        <div class="panel panel-default">
          <div class="panel-heading">
            {{repository}} 文件变更信息

            <el-tooltip content="历史补丁">
              <el-button size="small" type="text" icon="el-icon-receiving" @click="openPatchHistoryDialog" ></el-button>
            </el-tooltip>
            <el-tooltip content="模块信息">
              <el-button size="small" type="text" icon="el-icon-s-operation" @click="openModuleDialog" ></el-button>
            </el-tooltip>
          </div>
          <div class="panel-body">
            <div style="display: flex;align-items: center">
              <b >Maven Settings: </b>
              <connect-chose module="maven" ref="mavenConnect" v-model="mavenSettings" />
            </div>

            <vxe-table
              size="mini"
              border
              resizable
              row-id="path"
              :data="diffChangeTree"
              :loading="loading"
              :max-height="550"
              ref="diffChangeTree"
              :row-config="{useKey: true,keyField:'path',isCurrent: true,isHover: true}"
              :keyboard-config="{isArrow: true, isEnter: true}"
              :tree-config="{expandAll: true}">
              <vxe-column type="checkbox" :width="dynamicTreeTableWidth" title="路径" tree-node>
                <template #header="{row}">
                  路径
                  <el-button size="small" type="text" icon="el-icon-plus" @click="expandTreeAll"  />
                  <el-button size="small" type="text" icon="el-icon-minus" @click="$refs.diffChangeTree.clearTreeExpand()" />

                  <el-tooltip content="刷新变更文件树">
                    <el-button size="small" type="text" icon="el-icon-refresh" @click="refreshChoseCommit"></el-button>
                  </el-tooltip>

                  <el-tooltip content="下载选中文件补丁">
                    <el-button size="small" type="text" icon="el-icon-download" @click="downloadPatch"></el-button>
                  </el-tooltip>
                </template>
                <template #default="{row}">
                  <template v-if="row.changeType === 'ADD'">
                    <span class="text-forestgreen">{{row.fileName}}</span>
                  </template>
                  <template v-if="row.changeType === 'MODIFY'">
                    <span class="" style="color: #0097fb">{{row.fileName}}</span>
                  </template>
                  <template v-if="row.changeType === 'DELETE'">
                    <span class="" style="color: #8d8888"><s>{{row.fileName}}</s></span>
                  </template>
                  <template v-if="!!!row.changeType">
                    <template v-if="row.module">
                      <span class="text-bold"><i class="el-icon-pie-chart"></i> {{row.path}}</span>
                    </template>
                    <template v-else><span class="text-bold">{{row.path}}</span></template>
                    <el-tag class="margin-left" effect="dark" size="mini" type="info">{{row.fileCount}} files</el-tag>
                  </template>
                </template>
              </vxe-column>
              <vxe-column width="250" title="操作" fixed="right">
                <template #default="{row}">
                  <!-- 文件类型 -->
                  <template v-if="row.changeType">
                    <template v-if="row.changeType !== 'DELETE'">
                      <el-button type="text" v-if="row.fileName.toLowerCase().endsWith('java')" size="small" @click="javac([row.treeFilePath])">javac</el-button>
                      <el-button type="text" size="small" @click="downloadSource([row.treeFilePath])">下载</el-button>
                    </template>
                    <template v-else>
                      <span>占位</span>
                    </template>
                  </template>
                  <template v-else>
                    <template v-if="row.module">
                      <el-tooltip :content="'上次获取时间:' + (row.classpathResolveTime ? parseTime(row.classpathResolveTime) : '未获取')" placement="top">
                        <el-button type="text" size="small" @click="resolveJars(row.treeFilePath,row)" >classpath</el-button>
                      </el-tooltip>

                      <el-tooltip :content="'上次编译时间:'+(row.lastCompileTime ? parseTime(row.lastCompileTime) : '未编译')">
                        <el-button type="text" size="small" @click="execMavenGoals(row.treeFilePath,['clean','compile'])">compile</el-button>
                      </el-tooltip>
                      <el-button type="text" size="small"  @click="execMavenGoals(row.treeFilePath,['clean','install'])">install</el-button>
                      <!--                  <el-button type="text" size="small">批量编译</el-button>-->
                      <el-button type="text" size="small" @click="downloadSource([row.treeFilePath])">下载</el-button>
                    </template>
                    <template v-else>
                      <el-button type="text" size="small" @click="batchJavac(row)">批量编译</el-button>
                      <el-button type="text" size="small" @click="downloadSource([row.treeFilePath])">下载</el-button>
                    </template>
                  </template>
                </template>
              </vxe-column>
            </vxe-table>
          </div>
        </div>
      </el-row>

      <!-- 项目模块列表 -->
      <el-dialog :title="dialog.projectModule.title" :visible.sync="dialog.projectModule.visible" >
        <project-module :project-location="projectLoc"/>
      </el-dialog>

      <!-- 编译结果输出 -->
      <el-dialog :title="dialog.compileResult.title" fullscreen :visible.sync="dialog.compileResult.visible">
        <javac-result :compile-result="dialog.compileResult.data" />
      </el-dialog>

      <!-- classpath 结果展示 -->
      <el-dialog :title="dialog.classpathResult.title" :visible.sync="dialog.classpathResult.visible">
        <resolvejars :tree-files="dialog.classpathResult.data" />
      </el-dialog>

      <!-- 查看执行日志 -->
      <el-dialog fullscreen :visible.sync="dialog.mavenGoalLogDialog.visible" :title="dialog.mavenGoalLogDialog.title" @open="initMavenLog" @close="cascadeMavenLog" >
        <maven-exec-goal-log :file-path="dialog.mavenGoalLogDialog.filePath" ref="mavenLog"/>
      </el-dialog>

      <!-- bin 文件分析结果 -->
      <el-dialog :visible.sync="dialog.downBinFileDialog.visible" :title="dialog.downBinFileDialog.title">
        <bin-file-meta :meta="dialog.downBinFileDialog.data" :params="dialog.downBinFileDialog.params"/>
      </el-dialog>

      <!-- 补丁包记录 -->
      <el-dialog :visible.sync="dialog.patchHistoryDialog.visible" :title="dialog.patchHistoryDialog.title">
        <patch-history :group="group" :repository="repository" ref="patchHistory"/>
      </el-dialog>
    </div>
</template>

<script>
import vcs from '@/api/vcs'
import core from '@/api/core'

import TemplateExample from '@/views/database/code/TemplateExample'
import ConnectChose from '@/views/components/ConnectChose'
import projectModule from '@/views/call/vcs/git/projectModule'
import javacResult from '@/views/call/vcs/git/javacResult'
import resolvejars from '@/views/call/vcs/git/resolvejars'
import mavenExecGoalLog from '@/views/call/maven/mavenExecGoalLog'
import binFileMeta from '@/views/call/vcs/git/binFileMeta'
import patchHistory from '@/views/call/vcs/git/patchHistory'

import Vue from 'vue'
import 'xe-utils'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'

Vue.use(VXETable)

import {parseTime} from '@/utils'


export default {
  name: 'diffchange',
  components: { TemplateExample, ConnectChose, projectModule,javacResult,resolvejars, mavenExecGoalLog, binFileMeta, patchHistory},
  props: {
    group: String,
    repository: String,
    commits: Array
  },
  data(){
    return {
      diffChangeTree: [],
      struct: 'struct',
      loading: false,
      mavenSettings: null,
      dialog: {
        projectModule: {
          visible: false,
          title: '模块信息'
        },
        compileResult: {
          visible: false,
          title: '编译结果',
          data: {}
        },
        classpathResult: {
          visible: false,
          title: '获取 classpath 结果',
          data: []
        },
        mavenGoalLogDialog: {
          visible: false,
          title: '编译日志',
          filePath: null
        },
        downBinFileDialog: {
          visible: false,
          title: '打包文件下载结果',
          data: null,
          params: null
        },
        patchHistoryDialog: {
          visible: false,
          title: '补丁历史记录'
        }
      }
    }
  },
  methods: {
    expandTreeAll(){
      this.$nextTick(() => {
        console.log('展开所有')
        this.$refs.diffChangeTree.setAllTreeExpand(true)
      });
    },
    cascadeMavenLog(){
      this.$nextTick(() => {
        this.$refs.mavenLog.stopInterval()
      })
    },
    initMavenLog(){
      this.$nextTick(() => {
        this.$refs.mavenLog.init()
      })
    },
    parseTime,
    diffChanges(){
      let projectLocation = this.projectLocation()
      vcs.git.diffTree({projectLocation:projectLocation,commitIds: this.commits}).then(res => {
        this.diffChangeTree = [res.data]
        this.expandTreeAll()
      })
    },
    projectLocation(){
      return {
        group: this.group,
        repository: this.repository,
        path: ''
      }
    },
    javac(relativePaths){
      let projectLocation = this.projectLocation()
      this.loading = true
      vcs.project.compileLittleFiles({projectLocation,relativePaths}).then(res => {
        // console.log(res.data,'javac result')
        this.loading = false
        this.dialog.compileResult.data = res.data
        this.dialog.compileResult.visible = true
      }).catch(() => {
        this.loading = false
      })
    },
    batchJavac(row){
      let relativePaths = this.findChildPaths(row)
      this.javac(relativePaths)
    },
    findChildPaths(node){
      let paths = [];
      if (node && node.children && node.children.length){
        for (let i = 0; i < node.children.length; i++) {
          let item = node.children[i]
          if (item.file){
            paths.push(item.treeFilePath)
          }
          paths.concat(this.findChildPaths(item))
        }
      }
      return paths
    },
    resolveJars(relativePomFile,row){
      let settings = this.$refs.mavenConnect.getChoseConnect()
      if (!settings){
        this.$message({ type: 'error', message: '请先选择一个 Maven 设置'})
        return
      }
      let projectLocation = this.projectLocation();
      let moduleResolveDepParam = {settings,projectLocation,relativePomFile}
      this.loading = true
      vcs.project.resolveDependencies(moduleResolveDepParam).then(res => {
        // console.log(res.data,'resolveDependencies')
        this.loading = false

        this.dialog.classpathResult.data = [res.data]
        this.dialog.classpathResult.visible = true
        this.$set(row,'classpathResolveTime',new Date().getTime())
      }).catch(() => {
        this.loading = false
      })
    },
    execMavenGoals(relativePath,goals){
      let settings = this.$refs.mavenConnect.getChoseConnect()
      let projectLocation = this.projectLocation();
      let mavenGoalsParam = {settingsName: settings,projectLocation:projectLocation,relativePomFile: relativePath,goals: goals}
      vcs.project.executeGoals(mavenGoalsParam).then(res => {
        // console.log(res.data)
        this.dialog.mavenGoalLogDialog.visible = true
        this.dialog.mavenGoalLogDialog.filePath = res.data.outFilePath
      })
    },
    refreshChoseCommit(){
      this.diffChanges()
    },
    downloadPatch(){
      let selection = this.$refs['diffChangeTree'].getCheckboxRecords()
      // console.log(selection,'selection')
      // 过滤掉非文件的选中
      let relativePaths = selection.filter(item => item.file).map(item => item.treeFilePath)
      let tarFileParam = {projectLocation:this.projectLocation(),commitIds: this.commits,relativePaths: relativePaths,struct:this.struct}
      vcs.project.binFileParse(tarFileParam).then(res => {
        // core.fileDownload(res.data)
        this.dialog.downBinFileDialog.data = res.data
        this.dialog.downBinFileDialog.params = tarFileParam
        this.dialog.downBinFileDialog.visible = true
      })
    },
    openModuleDialog(){
      if (!this.repository){
        this.$message('请先选择一个仓库再进行此功能')
        return
      }
      this.dialog.projectModule.visible = true
      this.dialog.projectModule.title = this.repository+' 项目模块信息'
    },
    openPatchHistoryDialog(){
      this.dialog.patchHistoryDialog.visible = true

      this.$nextTick(() => {
        this.$refs['patchHistory'].listPatches()
      })
    },
    downloadSource(relativePaths){
      let tarFileParam = {projectLocation: this.projectLocation(),commitIds: this.commits,relativePaths: relativePaths,struct:this.struct}
      vcs.git.downloadSource(tarFileParam).then(res => {
        core.fileDownload(res.data)
      })
    },
    /**
     * 计算路径最大长度, 主要用于树形表格单元格换行问题的解决, 如果后面有更好的方案, 可以弃用此方案
     * @param diffChangeTree
     * @returns {number}
     */
    calcMaxPathLength(diffChangeTree){
      let leaves = this.findLeaves(diffChangeTree)
      // console.log(leaves,'leaves')
      const minLength = 250
      if (leaves.length === 0){
        return minLength;
      }

      let oneCharPerLength = 5
      let chars = leaves[0].length ;
      for (let i = 1; i < leaves.length; i++) {
          if (leaves[i].length > chars){
            chars = leaves[i].length
          }
      }
      if (oneCharPerLength * chars < minLength){
        return minLength;
      }
      return oneCharPerLength * chars + minLength;
    },
    findLeaves(diffChangeTree){
      if (!diffChangeTree || diffChangeTree.length === 0){
        return [];
      }
      let leaves = [];
      for (let i = 0; i < diffChangeTree.length; i++) {
        let item = diffChangeTree[i]
        if (!item.children || item.children.length === 0 ){
          leaves.push(item.treeFilePath)
          continue
        }
        leaves = leaves.concat(this.findLeaves(item.children))
      }

      return leaves
    }
  },
  watch: {
    commits: {
      handler(){
        this.diffChanges()
      }
    }
  },
  computed: {
    dynamicTreeTableWidth(){
      if (!this.diffChangeTree || this.diffChangeTree.length === 0 ){
        return 250
      }
      return this.calcMaxPathLength(this.diffChangeTree);
    },
    projectLoc(){
      return this.projectLocation()
    }
  }
}
</script>

<style scoped>
@import "../../../../assets/custom-theme/bootstrap.css";
</style>
